import 抽象语法树节点.*;
import 抽象语法树节点.表达式类.*;
import 抽象语法树节点.语句类.变量定义语句;
import 抽象语法树节点.语句类.块语句;
import 抽象语法树节点.语句类.赋值语句;

// 用于生成抽象语法树
public class 抽象语法树访问器 extends CymbolBaseVisitor<抽象语法树> {

    @Override
    public 抽象语法树 visitCompilationUnit(CymbolParser.CompilationUnitContext ctx) {
        var 节点 = new 抽象语法树[ctx.children.size()];

        for (var i = 0; i < 节点.length; i++) {
            节点[i] = visit(ctx.children.get(i));
        }

        return new 编译单元(节点);
    }

    @Override
    public 抽象语法树 visitStructDeclaration(CymbolParser.StructDeclarationContext ctx) {

        var 名称 = ctx.ID().getText();
        var 成员列表 = new 抽象语法树[ctx.structMember().size()];

        for (var i = 0; i < 成员列表.length; i++) {
            成员列表[i] = visit(ctx.structMember().get(i));
        }

        return new 结构体定义(名称, 成员列表);
    }

    @Override
    public 抽象语法树 visitStructMember(CymbolParser.StructMemberContext ctx) {
        if (ctx.type() != null)
            return new 结构体成员变量定义(ctx.ID().getText(), (类型) visitType(ctx.type()));
        else
            return visitStructDeclaration(ctx.structDeclaration());
    }

    @Override
    public 抽象语法树 visitMethodDeclaration(CymbolParser.MethodDeclarationContext ctx) {

        var 返回值类型 = (类型) visitType(ctx.type());
        var 方法名称 = ctx.ID().getText();
        var 语句块 = (块语句) visitBlock(ctx.block());

        if (ctx.formalParameters() == null) {
            return new 方法定义(方法名称, 返回值类型, null, 语句块);
        }

        var 参数列表 = new 方法参数[ctx.formalParameters().type().size()];
        for (var i = 0; i < 参数列表.length; i++) {
            var 参数类型 = (类型) visitType(ctx.formalParameters().type(i));
            var 参数名称 = ctx.formalParameters().ID(i).getText();
            参数列表[i] = new 方法参数(参数类型, 参数名称);
        }
        return new 方法定义(方法名称, 返回值类型, 参数列表, 语句块);
    }

    @Override
    public 抽象语法树 visitType(CymbolParser.TypeContext ctx) {
        return new 类型(ctx.getText()); // todo: 不知道这里需不需要特殊处理ID节点
    }

    @Override
    public 抽象语法树 visitBlock(CymbolParser.BlockContext ctx) {
        if (ctx.statement() == null) {
            return new 块语句(null);
        }

        var 语句列表 = new 抽象语法树[ctx.statement().size()];
        for (var i = 0; i < 语句列表.length; i++) {
            语句列表[i] = visitStatement(ctx.statement(i));
        }

        return new 块语句(语句列表);
    }

    @Override
    public 抽象语法树 visitVarDeclaration(CymbolParser.VarDeclarationContext ctx) {
        var 类型 = (类型) visitType(ctx.type());
        var 名称 = ctx.ID().getText();
        if (ctx.expression() == null) {
            return new 变量定义语句(名称, 类型, null);
        }

        var 表达式 = (表达式) visitExpression(ctx.expression());
        return new 变量定义语句(名称, 类型, 表达式);
    }

    @Override
    public 抽象语法树 visitStatement(CymbolParser.StatementContext ctx) {
        if (ctx.block() != null) {
            return visitBlock(ctx.block());
        }

        if (ctx.structDeclaration() != null) {
            return visitStructDeclaration(ctx.structDeclaration());
        }

        if (ctx.varDeclaration() != null) {
            return visitVarDeclaration(ctx.varDeclaration());
        }

        if (ctx.RETURN() != null) {
            return visitExpression(ctx.expression());
        }

        if (ctx.expression() == null) {
            return visit(ctx.postfixExpression());
        }

        return new 赋值语句((表达式) visit(ctx.postfixExpression()), (表达式) visitExpression(ctx.expression()));
    }

    @Override
    public 抽象语法树 visitAddExpression(CymbolParser.AddExpressionContext ctx) {
        var 参数列表 = new 表达式[ctx.postfixExpression().size()];
        for (var i = 0; i < 参数列表.length; i++) {
            参数列表[i] = (表达式) visit(ctx.postfixExpression(i));
        }

        return new 加法表达式(参数列表);
    }

    @Override
    public 抽象语法树 visitCallExpression(CymbolParser.CallExpressionContext ctx) {
        var 参数列表 = new 表达式[ctx.expressionList().expression().size()];
        for (var i = 0; i < 参数列表.length; i++) {
            参数列表[i] = (表达式) visit(ctx.expressionList().expression(i));
        }

        return new 方法调用表达式(ctx.ID().getText(), 参数列表);
    }

    @Override
    public 抽象语法树 visitMemeberExpression(CymbolParser.MemeberExpressionContext ctx) {

        // 左结合（右递归）的一棵树

        成员访问表达式 结果 = null;
        成员访问表达式 当前表达式 = null;
        for (var i = 0; i < ctx.ID().size() - 1; i++) {
            var 新表达式 = new 成员访问表达式();
            新表达式.符号引用 = new 符号引用表达式(ctx.ID().get(i).getText());

            if (当前表达式 == null) {
                结果 = 新表达式;
                当前表达式 = 新表达式;
            } else {
                当前表达式.成员 = 新表达式;
                当前表达式 = 新表达式;
            }
        }

        if (当前表达式 == null) return null;
        当前表达式.成员 = new 符号引用表达式(ctx.ID().get(ctx.ID().size() - 1).getText());
        return 结果;
    }

    @Override
    public 抽象语法树 visitReferenceExpression(CymbolParser.ReferenceExpressionContext ctx) {
        return new 符号引用表达式(ctx.ID().getText());
    }

    @Override
    public 抽象语法树 visitLiteralExpression(CymbolParser.LiteralExpressionContext ctx) {
        return new 整数字面量表达式(Integer.parseInt(ctx.INT().getText()));
    }
}
